<?php

use Godruoyi\Snowflake\Snowflake;
use think\Cache;
use think\db\Connection;
use think\db\exception\DbException;

if (!function_exists('antiShake')) {
    /**
     * 防抖
     * @param int $userId 用户ID
     * @param int $productId 产品ID
     * @param int $expire 防抖时间, 默认1秒
     * @param string|null $mark 标识符, 通过拼接标识符、用户ID、产品ID来确定唯一键。标识符可不填写
     * @return bool 存在重复提交返回False, 不存在则返回True
     */
    function antiShake(int $userId, int $productId, int $expire = 1, string $mark = null): bool
    {
        $key = is_null($mark) ? $userId . '::' . $productId : $mark . '::' . $productId . '::' . $mark;
        return !Cache::store('redis')->has($key) && Cache::store('redis')->set($key, $productId, $expire);
    }
}

if (!function_exists('generateOrderId')) {
    /**
     * 生成订单号
     * @param string $prefix 订单前缀
     * @return string 订单前缀(X字节) + 年月日时分秒毫秒(十五字节) + 序列号(四字节)
     */
    function generateOrderId(string $prefix = 'D'): string
    {
        $snowflake = new Snowflake(1, 1);
        $sequence = $snowflake->parseId($snowflake->id())['sequence'];
        $microtime = microtime(true);

        // 直接获取包含毫秒的时间戳字符串
        $dateTime = date('ymdHis') . sprintf('%03d', ($microtime - floor($microtime)) * 1000);
        return $prefix . $dateTime . str_pad(mt_rand(0, 9999), 4, '0', STR_PAD_LEFT);
    }
}

if (!function_exists('incCosts')) {
    /**
     *  增加贡献值
     * @param Connection $qd 数据库句柄
     * @param int $money 抽成金额
     * @param int $userId 用户ID
     * @param int $companyId 公司ID
     * @param int $before 变更前余额
     * @param string $source 来源
     * @param string $memo 备注
     * @param bool $type 是否增加公司费用
     * @return void
     * @throws Exception
     * @throws DbException
     */
    function incCosts(Connection $qd, int $money, int $userId, ?int $companyId, int $before, string $source, string $memo, bool $type = false): void
    {
        $insert = ['user_id' => $userId, 'money' => $money, 'before' => $before, 'after' => $before + $money, 'source' => $source, 'memo' => $memo, 'createtime' => time()];
        if ($type) {
            $table = 'fa_department';
            $logTable = 'fa_department_money_log';
            $insert['company_id'] = $companyId;
            $id = $companyId;
        } else {
            $table = 'fa_user';
            $logTable = 'fa_user_money_log';
            $id = $userId;
        }
        $num = $qd->table($table)->where('id', $id)->setInc('money', $money);
        if (!$num && $money != 0) throw new Exception('服务错误');
        $num = $qd->table($logTable)
            ->insert($insert);
        if (!$num) throw new Exception('服务错误');
    }
}

if (!function_exists('decCosts')) {
    /**
     *  扣除数据能量
     * @param Connection $qd 数据库句柄
     * @param int $money 抽成金额
     * @param int $userId 用户ID
     * @param int $companyId 公司ID
     * @param int $before 变更前余额
     * @param string $source 来源
     * @param string $memo 备注
     * @param bool $type 是否增加公司费用
     * @return void
     * @throws Exception
     * @throws DbException
     */
    function decCosts(Connection $qd, int $money, int $userId, ?int $companyId, int $before, string $source, string $memo, bool $type = false)
    {
        $insert = ['user_id' => $userId, 'score' => -$money, 'before' => $before, 'after' => $before - $money, 'source' => $source, 'memo' => $memo, 'createtime' => time()];
        if ($type) {
            $table = 'fa_department';
            $logTable = 'fa_department_score_log';
            $insert['company_id'] = $companyId;
            $id = $companyId;
        } else {
            $table = 'fa_user';
            $logTable = 'fa_user_score_log';
            $id = $userId;
        }
        $num = $qd->table($table)->where('id', $id)->setDec('score', $money);
        if (!$num && $money != 0) throw new Exception('扣费失败, 请重新支付订单');
        $num = $qd->table($logTable)
            ->insert($insert);
        if (!$num) throw new Exception('扣费失败, 请重新支付订单');
    }
}